const array = [1, 2, 3, 4, 5];

console.log(array.__proto__)  // [object Array]

console.log(Array.prototype)  // [object Array]

console.log(Array.prototype.constructor)  // [Function: Array]

console.log(Object.getPrototypeOf(array))    // [object Array]



function Person(name) {
  this.name = name
 }
 Person.prototype.getName = function() {}
 console.log(Person.prototype.__proto__)  // [Object: null prototype] {}
 var p = new Person('hello')
 console.log(p.__proto__)  //  { getName: [Function (anonymous)] }
 console.log(p.__proto__ === Person.prototype)  // true
 console.log(p.__proto__ === p.constructor.prototype)  // true


//  直接给Person的原型对象直接⽤对象赋值
 Person.prototype = {
   getName: function() {}
}
var p = new Person('hello')
console.log(p.__proto__ === Person.prototype)  // true
// 直接给Person的原型对象直接⽤对象赋值时，它的构造函数指向的了根构造函数Object，所以这时候p.constructor === Object ，⽽不是 p.constructor === Person 。
console.log(p.__proto__ === p.constructor.prototype)  // false

// 修改回来

p.constructor = Person
console.log(p.__proto__ === Person.prototype) // true
console.log(p.__proto__ === p.constructor.prototype) // true


console.log(p.__proto__) // { getName: [Function: getName] }
console.log(p.constructor.prototype) // { getName: [Function: getName] }
console.log(Person.prototype.__proto__)  // [Object: null prototype] {}
console.log(p.__proto__.__proto__)  // [Object: null prototype] {}
console.log(p.__proto__.constructor.prototype.__proto__)  // null
console.log(Person.prototype.constructor.prototype.__proto__)  // null
console.log(Person.prototype.constructor)  // [Function: Object]
 


// 原型链终点  ---- null
console.log(Object.prototype.__proto__)

// 获得对象⾮原型链上的属性  hasOwnProperty()
// 通过构造函数获得的属性都是自己的属性， 原型链上的属性是通过原型链获得的， 
console.log(p.hasOwnProperty('name'))  // true
console.log(p.hasOwnProperty('getName'))  // false